Skip to content

Guard global rate limiting against the FastAPI 0.137+ regression - #86

Closed
amrtgaber wants to merge 2 commits into
mainfrom
guard-default-rate-limits
Closed

Guard global rate limiting against the FastAPI 0.137+ regression#86
amrtgaber wants to merge 2 commits into
mainfrom
guard-default-rate-limits

Conversation

@amrtgaber

Copy link
Copy Markdown
Contributor

FastAPI ≥0.137 materializes included routers' routes lazily, which silently disables slowapi's SlowAPIMiddleware enforcement of default_limits on undecorated routes — which is every /v1 route in this service. All 26 existing tests stay green when it happens (slowapi issue #281, open fix PR #282).

This PR makes the failure impossible to ship unnoticed:

  • Canary test: 60 requests to /v1/armor succeed, the 61st must 429. Empirically verified to fail on fastapi 0.140.7 and pass on the current lock.
  • Exempt test: / and /health never 429.
  • Limiter reset fixture in conftest so the canary's request count doesn't leak into other tests.
  • Resolver constraints fastapi<0.136, starlette<1.0 with the unpin condition documented: a slowapi release containing the #282 fix (Dependabot will surface the slowapi bump).

A separate stacked PR applies the toolchain/Python 3.14 refresh on top of this protection.

FastAPI >=0.137 resolves included routers' routes lazily, which breaks
slowapi's SlowAPIMiddleware enforcement of default_limits on undecorated
routes — every /v1 route here — while all existing tests stay green
(slowapi issue #281, fix PR #282 open upstream).

Add a canary test asserting the 60/min default actually bites on an
undecorated route (verified to fail on fastapi 0.140.7 and pass on the
current lock), a limiter-reset fixture so its request count doesn't leak
across tests, and resolver constraints holding fastapi below 0.136 and
starlette below 1.0 until a fixed slowapi release ships.
Refresh the lockfile within the rate-limit guard constraints (fastapi
stays 0.135.x, starlette 0.52; OpenTelemetry, structlog 26, wrapt 2 and
the rest move to latest), update the ruff pre-commit hook from v0.8.6 to
v0.16.0 with the ruff-check id and apply its fixes, and move to Python
3.14 across .python-version, requires-python, ruff target-version, and
the Docker base image; all compiled dependencies ship cp314 wheels. Pin
the Dockerfile uv stage, bump CI to checkout@v7 and setup-uv@v9.0.0 (no
v9 alias tag exists), and add weekly grouped Dependabot updates. The dev
compose Postgres stays on 16 pending a coordinated production upgrade.
@amrtgaber

Copy link
Copy Markdown
Contributor Author

Superseded — content landed via the restore PR after the stacked-rebase mistake.

@amrtgaber amrtgaber closed this Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant